/*********************************************************************************
 *      Copyright:  (C) 2023 LN
 *                  All rights reserved.
 *
 *       Filename:  logger.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(2023年04月13日)
 *         Author:  Li Haipeng <NULL>
 *      ChangeLog:  1, Release initial version on "2023年04月13日 16时30分47秒"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <stdarg.h>
#include "logger.h"


extern const char   *__progname;
#define PROGRAM_NAME __progname


typedef struct logger_s{
    FILE    *fd;
    int	     loglevel;
    int	     use_stdout;
}logger_l;


static struct 	  logger_s g_logger;
static char		 *log_name = NULL;
static int		  g_size = 65535;

static const char *LOG_LEVELS[]={
    LOG_STRING_ERROR,
    LOG_STRING_WARN,
    LOG_STRING_INFO,
    LOG_STRING_DEBUG
};


int logger_init(char *filename,int loglevel)
{
    logger_term();
	
    g_logger.loglevel = loglevel > LOG_LEVEL_MAX ? LOG_LEVEL_MAX : loglevel;

    if( !filename || !strcasecmp(filename,"stdout"))
    {
        g_logger.use_stdout = 1;
        g_logger.fd = stderr;;
    }
    else
    {
        g_logger.use_stdout = 0;
        g_logger.fd = fopen(filename,"a");
        if( !g_logger.fd )
        {
            fprintf(stderr,"Failed to open '%s':'%s'", filename, strerror(errno));
            return -1;
        }
		log_name = filename;
    }


    return 0;
}

void logger_term(void)
{
    if( !g_logger.fd )
    {
        return ;
    }

    if( !g_logger.use_stdout )
    {
        fclose(g_logger.fd);
    }

    g_logger.use_stdout = 0;
    g_logger.fd = NULL;

    return;
}

void log_generic(const int level,const char *format, va_list args)
{
    char            message[256];
    char            date[32];
    struct tm       *current_tm = NULL;
    time_t          time_now;


    vsprintf(message, format, args);

    time(&time_now);
    current_tm = localtime(&time_now);
    strftime(date,sizeof(date),"%F %T", current_tm);

    int res = fprintf(g_logger.fd,"%s : %s [%s] %s\n", PROGRAM_NAME, date, LOG_LEVELS[level], message);

    fflush(g_logger.fd);
}


void log_error(char *format, ...)
{
	if( log_name )
	{
		logger_back(log_name);
	}
    if(g_logger.loglevel < LOG_LEVEL_ERROR)
    {
        return;
    }
    va_list args;
    va_start(args, format);
    log_generic(LOG_LEVEL_ERROR, format, args);
    va_end(args);
}

void log_warn(char *format, ...)
{
	if( log_name )
	{
		logger_back(log_name);
	}
    if(g_logger.loglevel < LOG_LEVEL_WARN)
    {
        return;
    }

    va_list args;
    va_start(args, format);
    log_generic(LOG_LEVEL_WARN, format, args);
    va_end(args);
}

void log_info(char *format, ...)
{
	if( log_name )
	{
		logger_back(log_name);
	}
    if(g_logger.loglevel < LOG_LEVEL_INFO)
    {
        return;
    }

    va_list args;
    va_start(args, format);
    log_generic(LOG_LEVEL_INFO, format, args);
    va_end(args);
}
void log_debug(char *format, ...)
{
	if( log_name )
	{
		logger_back(log_name);
	}
    if(g_logger.loglevel < LOG_LEVEL_DEBUG)
    {
        return;
    }

    va_list args;
    va_start(args, format);
    log_generic(LOG_LEVEL_DEBUG, format, args);
    va_end(args);
}

int logger_back(char *filename)
{
    FILE            *fd = NULL;
    int	             d;
    struct stat      statbuf;


    stat(filename, &statbuf);
    d = statbuf.st_size;
    if(d > g_size)
    {
        fd = fopen(filename,"w");
        fclose(fd);
        printf("roll back!\n");
    }
    return 0;
}
